﻿using System.Collections.Generic;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using AMail.Common;
using AMail.Common.Interfaces.Services;
using Elentok.Common.Wpf.Services;
using Microsoft.Practices.Composite.Presentation.Commands;

namespace AMail.Modules.Archive
{
  public class ArchiveCommandsBuilder
  {
    private IArchiveService archiveService;
    private IMenuService menuService;
    private IKeybindingService keybindingService;

    public ArchiveCommandsBuilder(IArchiveService archiveService,
      IMenuService menuService,
      IKeybindingService keybindingService)
    {
      this.archiveService = archiveService;
      this.menuService = menuService;
      this.keybindingService = keybindingService;
    }

    #region Public Methods

    /// <summary>
    /// Registers the commands in the menu
    /// </summary>
    public List<DelegateCommand<object>> CreateAndRegisterCommands()
    {
      List<DelegateCommand<object>> commands = new List<DelegateCommand<object>>();
      RegisterFileMenuCommands(commands);
      RegisterEditMenuCommands(commands);
      return commands;
    }

    #endregion

    private void RegisterFileMenuCommands(List<DelegateCommand<object>> commands)
    {
      #region New Command

      var newCommand = new DelegateCommand<object>(
        delegate { this.archiveService.CreateNewArchive(); });
      commands.Add(newCommand);
      menuService.RegisterMenuItem(MenuNames.FileMenu,
        new MenuItem
        {
          Header = "_New Archive...",
          Icon = new Image
          {
            Source = new BitmapImage(ResourceUris.Page)
          },
          InputGestureText = "Ctrl+N",
          Command = newCommand
        });

      keybindingService.RegisterCommand(WindowNames.MainWindow, newCommand,
        new KeyGesture(Key.N, ModifierKeys.Control));

      #endregion

      #region Open Command
      var openCommand = new DelegateCommand<object>(
        delegate { this.archiveService.OpenArchive(); });
      commands.Add(openCommand);
      menuService.RegisterMenuItem(MenuNames.FileMenu,
        new MenuItem
        {
          Header = "_Open Archive...",
          Icon = new Image
          {
            Source = new BitmapImage(ResourceUris.Folder)
          },
          InputGestureText = "Ctrl+O",
          Command = openCommand
        });

      keybindingService.RegisterCommand(WindowNames.MainWindow, openCommand, new KeyGesture(Key.O, ModifierKeys.Control));
      #endregion

      #region Save Command
      var saveCommand = new DelegateCommand<object>(
        delegate { this.archiveService.SaveActiveArchive(); },
        delegate { return this.archiveService.ActiveArchiveHasUnsavedChanges; } );
      commands.Add(saveCommand);
      menuService.RegisterMenuItem(MenuNames.FileMenu,
        new MenuItem
        {
          Header = "_Save Archive",
          Icon = new Image
          {
            Source = new BitmapImage(ResourceUris.Disk)
          },
          InputGestureText = "Ctrl+S",
          Command = saveCommand
        });

      keybindingService.RegisterCommand(WindowNames.MainWindow, saveCommand, new KeyGesture(Key.S, ModifierKeys.Control));
      #endregion

      #region Close Command
      var closeCommand = new DelegateCommand<object>(
        delegate { this.archiveService.CloseActiveArchive(); },
        delegate { return this.archiveService.ActiveArchive != null; });
      commands.Add(closeCommand);

      menuService.RegisterMenuItem(MenuNames.FileMenu,
        new MenuItem
        {
          Header = "_Close Archive",
          Command = closeCommand
        });
      #endregion

      #region Revert to saved version
      var revertCommand = new DelegateCommand<object>(
        delegate { this.archiveService.Revert(); },
        delegate { return this.archiveService.ActiveArchiveHasUnsavedChanges; });
      commands.Add(revertCommand);

      menuService.RegisterMenuItem(MenuNames.FileMenu,
        new MenuItem
        {
          Header = "_Revert to saved version",
          Command = revertCommand,
          Icon = new Image
          {
            Source = new BitmapImage(ResourceUris.RotateClockwise)
          }
        });
      #endregion

      #region Change password
      var changePasswordCommand = new DelegateCommand<object>(
        delegate { this.archiveService.ChangePassword(); },
        delegate { return this.archiveService.ActiveArchive != null; });
      commands.Add(changePasswordCommand);

      menuService.RegisterMenuItem(MenuNames.FileMenu,
        new MenuItem
        {
          Header = "_Change Password...",
          Command = changePasswordCommand,
          Icon = new Image
          {
            Source = new BitmapImage(ResourceUris.Key)
          }
        });
      #endregion
    }

    private void RegisterEditMenuCommands(List<DelegateCommand<object>> commands)
    {
      #region Undo Command
      var undoCommand = new DelegateCommand<object>(
        delegate { this.archiveService.ActiveArchive.Undo(); },
        delegate { return this.archiveService.ActiveArchiveHasUnsavedChanges; });
      commands.Add(undoCommand);

      this.menuService.RegisterMenuItem(MenuNames.EditMenu,
        new MenuItem
        {
          Header = "_Undo",
          Icon = new Image
          {
            Source = new BitmapImage(ResourceUris.RotateClockwise)
          },
          InputGestureText = "Ctrl+Z",
          Command = undoCommand
        });

      this.keybindingService.RegisterCommand(WindowNames.MainWindow, undoCommand,
        new KeyGesture(Key.Z, ModifierKeys.Control));
      #endregion
    }
  }
}
